from passive_parser import *
import xml.sax.saxutils


# algebraic datatype




style_only_tags = ["font", "span"]
decor_tags = "b i u em strong strike".split(" ")

inline_tags = set(style_only_tags+decor_tags)

style_resetter_tags = "table tr td".split(" ")



def reconst_tag(tag, attrs, container=True):
    texttags = []
    for n,v in attrs:
        texttags.append(" {0}={1}".format(n,xml.sax.saxutils.quoteattr(v)))
    endslash = "" if container else "/"
    return "<{0}{1}{2}>".format(tag,"".join(texttags), endslash)

def process_attrs(tag, attrs, skip_attrs):
    res = []
    for x in attrs:
        if tag+"/"+x[0] in skip_attrs:
            continue
        if tag+"/"+x[0]+"="+x[1] in skip_attrs:
            continue
            
        res.append(x)
    return res


def update_style(oldstyle, tag, attrs, skip_attrs):
    if tag in style_resetter_tags:
        return {}
    style = copy(oldstyle)
    attrs = process_attrs(tag, attrs, skip_attrs)
    style.update([(tag+"/"+x,y) for (x,y) in attrs])
    if tag in decor_tags:
        style.update([(tag+"/","")])
    if (style==oldstyle):
        return oldstyle # recycle memory
    return style

def get_essential_tags(chain):
    return [pair for pair in chain if pair[0] not in style_affecting_tags]

sink = open("debug.txt","wt")

def render_styled_text(text, style):
    s = []
    stack = []
    for param in sorted(style.keys()):
        tag, attr = param.split("/")
        if attr:
            s.append(reconst_tag(tag, [(attr, style[param])]))
        else:
            s.append(reconst_tag(tag, []))
        stack.append(tag)
    s.append(text)
    stack.reverse()
    for tag in stack:
        s.append("</{0}>".format(tag))
    return "".join(s)

def convert_from_html32(inputfile, outfile, skip_attrs=[]):
    block_tag_chain = []
    style_chain = [{}]
    out_buffer = []
    style_of_buffer = {}
    
    def flush(out_buffer, style_of_buffer):
        if len(out_buffer):
            outfile.write(render_styled_text("".join(out_buffer), style_of_buffer))
    
    for entry in passive_parse(inputfile):
        etype = entry[0]
        if etype==V_START:
            d, tag, attrs = entry
            if tag in inline_tags:
                style_chain.append(update_style(style_chain[-1], tag, attrs, skip_attrs))
            else:
                flush(out_buffer, style_of_buffer)
                style_of_buffer = style_chain[-1]
                out_buffer = []
                outfile.write(reconst_tag(tag, attrs))
        if etype==V_END:
            d, tag = entry
            if tag in inline_tags:
                style_chain.pop()
            else:
                flush(out_buffer, style_of_buffer)
                style_of_buffer = style_chain[-1]
                out_buffer = []
                outfile.write("</{0}>".format(tag))
        if etype==V_STANDALONE:
            d, tag, attrs = entry
            flush(out_buffer, style_of_buffer)
            style_of_buffer = style_chain[-1]
            out_buffer = []
            outfile.write(reconst_tag(tag, attrs))
        if etype==V_TEXT:
            d, text = entry
            if style_chain[-1]==style_of_buffer:
                out_buffer.append(text)
            else:
                flush(out_buffer, style_of_buffer)
                out_buffer = [text]
                style_of_buffer = style_chain[-1]
    if len(out_buffer):
        outfile.write(render_styled_text("".join(out_buffer), style_of_buffer))
            
        
